package tecpointbenchmark.model;

import java.util.ArrayList;
import java.util.Observable;
import tecpointbenchmark.model.modules.*;
import tecpointbenchmark.model.dto.*;

/**
 * Knows all benchmark modules, and if one is currently running.
 * 
 * @author Rafel & Tom
 */
public class ModuleHandler extends Observable {
	private static ArrayList<BenchmarkModule> modules;
	private static BenchmarkModule runningModule;
	private static RunManager runManager;
	private static ReportHandler reportHandler;

	public ModuleHandler() {
		runManager = new RunManager(this);
		modules = new ArrayList<BenchmarkModule>();
		reportHandler = new ReportHandler();

		ResultDTO hddResult = new ResultDTO();
		ResultDTO ramResult = new ResultDTO();
		ResultDTO singleThreadIntegerResult = new ResultDTO();
		ResultDTO singleThreadFloatResult = new ResultDTO();
		ResultDTO multiThreadFloatResult = new ResultDTO();
		//ResultDTO grafikResultat = new ResultDTO();
                ResultDTO grafik3DResultat = new ResultDTO();

		BenchmarkModule hddModule = new HDDModule(hddResult);
		BenchmarkModule ramModule = new RAMModule(ramResult);
		BenchmarkModule singleThreadIntegarModule = new SingleThreadIntegerModule(
				singleThreadIntegerResult);
		BenchmarkModule singleThreadFloatModule = new SingleThreadFloatModule(
				singleThreadFloatResult);
		BenchmarkModule multiThreadFloatModule = new MultiThreadFloatModule(
				multiThreadFloatResult);
		//BenchmarkModule grafik = new IntermediateGraphics(grafikResultat);
                BenchmarkModule grafik3D = new GFX3DModuleShell(grafik3DResultat);

		modules.add(hddModule);
		modules.add(singleThreadIntegarModule);
		modules.add(singleThreadFloatModule);
		modules.add(multiThreadFloatModule);
		modules.add(ramModule);
		//modules.add(grafik);
        modules.add(grafik3D);
	}

	/*
	 * Creates an array of ModuleInfoDTO's from all the BenchmarkModules and
	 * returns it. The id in ModuleInfoDTO matches the index of the module in the
	 * modules array.
	 */
	public ArrayList<ModuleInfoDTO> getModules() {
		ArrayList<ModuleInfoDTO> ar = new ArrayList<ModuleInfoDTO>();
		for (BenchmarkModule bm : modules) {
			ar.add(new ModuleInfoDTO(bm.getShortDescription(), bm
					.getLongDescription(), bm.getModName(), modules.indexOf(bm)));
		}
		return ar;
	}

	/**
	 * Runs the benchmark
	 * 
	 * @param moduleIndex
	 *            The index in the array of modules that you want to run.
	 */
	public void runBenchmark(int moduleIndex) {
		runningModule = modules.get(moduleIndex);
		runManager.startTimer(5000);
		// runManager.startTimer(System.currentTimeMillis());
		runningModule.start();
	}

	/**
	 * Stops the currently running benchmark
	 */
	public void stopBenchmark(boolean b) {

		// Stop the benchmarking
		runningModule.stopBenchmark();
		runManager.stopTimer();
		
		ResultDTO currentResult = runningModule.getResult();

		// Where did the call come from?
		// If call came from USER
		if (!b)
			// setNumber(1) = the user aborted the benchmark
			currentResult.setNumber(1);
		// If call came from TIMER
		else
			// setNumber(0) = the timer timed out
			currentResult.setNumber(0);

		while (currentResult.getPoints() == 0) {
			try {
				Thread.sleep(50);
			} catch (InterruptedException e) {
				System.out.println(e);
			}
		}
		
		reportHandler.writeReport(currentResult);
		
		if (tecpointbenchmark.startup.Main.debug) {
            System.out.println("Notifying observers...");
        }
		
		setChanged();
		notifyObservers(currentResult);
	}

	/**
	 * Fetches the result from the module
	 * 
	 * @return The result from the module
	 */
	public ResultDTO getModuleState() {
		return runningModule.getResult();
	}
}
